package com.quick.develop.flowable.application.impl;

import com.quick.develop.flowable.constant.BpmConstants;
import com.quick.develop.flowable.domain.dto.task.BpmTaskDTO;
import com.quick.develop.flowable.enums.BpmTaskCategory;
import com.quick.develop.framework.utils.StringUtils;
import com.quick.develop.flowable.application.IBpmManageApplication;
import com.quick.develop.flowable.application.IBpmTaskAssigneeApplication;
import com.quick.develop.flowable.domain.manage.BpmManageReqVO;
import com.quick.develop.flowable.framework.cmd.ClearTaskDescCmd;
import com.quick.develop.flowable.framework.cmd.SetTaskDescCmd;
import com.quick.develop.flowable.framework.cmd.admin.CancelProcessCmd;
import com.quick.develop.flowable.framework.cmd.admin.DeleteProcessCascadeCmd;
import com.quick.develop.flowable.framework.cmd.admin.ProcessChangeStateCmd;
import com.quick.develop.flowable.framework.convert.task.BpmTaskConvert;
import com.quick.develop.flowable.framework.factory.FlowServiceFactory;
import com.quick.develop.flowable.service.task.IBpmPermissionService;
import com.quick.develop.flowable.service.task.IBpmTaskService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static com.quick.develop.flowable.enums.BpmErrorCodeConstants.*;
import static com.quick.develop.framework.common.utils.ServiceExceptionUtils.exception;
import static com.quick.develop.framework.utils.collection.CollectionUtils.convertSet;

/**
 * @author junyuan.liu
 * @description:
 * @date 2022/9/14 10:26
 */
@Slf4j
@Component
public class BpmManageApplicationImpl extends FlowServiceFactory implements IBpmManageApplication {
    @Resource
    IBpmPermissionService bpmPermissionService;

    @Resource
    IBpmTaskService bpmTaskService;

    @Resource
    IBpmTaskAssigneeApplication bpmTaskAssigneeApplication;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInstances(BpmManageReqVO reqVO) {
        String processInstanceId = reqVO.getProcessInstanceId();
        if (StringUtils.isEmpty(processInstanceId)) {
            throw exception(PROCESS_INSTANCE_ID_EMPTY);
        }
        if (StringUtils.isEmpty(reqVO.getBusinessKey())) {
            throw exception(PROCESS_BUSINESS_KEY_EMPTY);
        }
        bpmPermissionService.isAdminOnException();
        managementService.executeCommand(new DeleteProcessCascadeCmd(processInstanceId, reqVO.getBusinessKey()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignTask(BpmManageReqVO reqVO) {
        bpmPermissionService.isAdminOnException();
        Task task = bpmTaskService.getTaskById(reqVO.getTaskId());
        String taskId = task.getId();
        // 先释放
        Optional.ofNullable(task.getClaimTime()).ifPresent(t -> taskService.unclaim(taskId));
        managementService.executeCommand(new ClearTaskDescCmd(taskId, BpmTaskCategory.CANDIDATE.getCode()));

        taskService.setAssignee(taskId, reqVO.getAssignee());
        // 标记一下
        managementService.executeCommand(new SetTaskDescCmd(taskId, BpmConstants.ADMIN_ASSIGN));
    }

    @Override
    public List<BpmTaskDTO> getTaskListByProcessInstanceId(String processInstanceId) {
        List<Task> list = bpmTaskService.getTasksByProcessInstanceId(processInstanceId);
        Set<String> var1 = convertSet(list, Task::getAssignee);
        Map<String, String> users = bpmTaskAssigneeApplication.getUsersNameByUserCode(var1);

        return BpmTaskConvert.INSTANCE.convertList5(list, users);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void jumpProcess(BpmManageReqVO reqVO) {
        bpmPermissionService.isAdminOnException();
        if (StringUtils.isEmpty(reqVO.getProcessInstanceId())) {
            throw exception(PROCESS_INSTANCE_ID_EMPTY);
        }
        managementService.executeCommand(new ProcessChangeStateCmd(reqVO.getProcessInstanceId(), reqVO.getTargetActId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unClaimTask(BpmManageReqVO reqVO) {
        bpmPermissionService.isAdminOnException();
        taskService.setVariableLocal(reqVO.getTaskId(), BpmConstants.ENTRUST_IGNORE, BpmConstants.ENTRUST_IGNORE);
        taskService.unclaim(reqVO.getTaskId());
        // 标记一下
        managementService.executeCommand(new SetTaskDescCmd(reqVO.getTaskId(), BpmConstants.ADMIN_UN_CLAIM));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelInstance(BpmManageReqVO reqVO) {
        bpmPermissionService.isAdminOnException();
        managementService.executeCommand(new CancelProcessCmd(reqVO.getProcessInstanceId()));
    }
}
